﻿using PRO.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace PRO.Controls
{
    [AspNetHostingPermissionAttribute(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [ToolboxData("<{0}:SortControl runat=server></{0}:SortControl>")]
    public class SortControl : CompositeControl
    {

        #region 属性
        [CategoryAttribute("排序设置"),
        Bindable(true),
        DefaultValue(""),
        Description("操作的表名"),
        Localizable(true)]
        public string TableName
        {
            get
            {
                return (String)ViewState["Sort_TableName"];
            }
            set
            {
                ViewState["Sort_TableName"] = value.ToString();
            }
        }
        [CategoryAttribute("当前行数，用于跨行移动"),
      Bindable(true),
      Description("当前行数"),
      Localizable(true)]
        public int RowIndex
        {
            get
            {
                if (ViewState["Sort_RowIndex"] == null || (String)ViewState["Sort_RowIndex"] == "")
                    return -1;
                return int.Parse(ViewState["Sort_RowIndex"].ToString());
            }
            set
            {
                ViewState["Sort_RowIndex"] = value.ToString();
            }
        }

        [CategoryAttribute("行数，用于跨行移动"),
      Bindable(true),
      Description("行数"),
      Localizable(true)]
        public int RowCount
        {
            get
            {
                if (ViewState["Sort_RowCount"] == null || (String)ViewState["Sort_RowCount"] == "")
                    return 0;
                return int.Parse(ViewState["Sort_RowCount"].ToString());
            }
            set
            {
                ViewState["Sort_RowCount"] = value.ToString();
            }
        }



        [CategoryAttribute("当前排序的序号"),
      Bindable(true),
      DefaultValue(-1),
      Description("当前排序的序号"),
      Localizable(true)]
        public int Sort
        {
            get
            {
                if (ViewState["Sort_SortNumber"] == null || (String)ViewState["Sort_SortNumber"] == "")
                    return -1;
                return int.Parse(ViewState["Sort_SortNumber"].ToString());
            }
            set
            {
                ViewState["Sort_SortNumber"] = value.ToString();
            }
        }


        [CategoryAttribute("当前ID"),
       Bindable(true),
       DefaultValue(-1),
       Description("当前编号"),
       Localizable(true)]
        public int ItemID
        {
            get
            {
                if (ViewState["Sort_ItemID"] == null || (String)ViewState["Sort_ItemID"] == "")
                    return -1;
                return int.Parse(ViewState["Sort_ItemID"].ToString());
            }
            set
            {
                ViewState["Sort_ItemID"] = value.ToString();
            }
        }

        [CategoryAttribute("排序设置"),
        Bindable(true),
        DefaultValue(""),
        Description("排序表的主键列名"),
        Localizable(true)]
        public string KeyField
        {
            get
            {
                if (ViewState["Sort_KeyField"] == null || (String)ViewState["Sort_KeyField"] == "")
                    return "";
                return (String)ViewState["Sort_KeyField"];
            }
            set
            {
                ViewState["Sort_KeyField"] = value.ToString();
            }
        }
        [CategoryAttribute("排序设置"),
        Bindable(true),
        DefaultValue(""),
        Description("排序时的过滤条件（sql语句），例如：type=5"),
        Localizable(true)]
        public string Filter
        {
            get
            {
                return (String)ViewState["Sort_Filter"];
            }
            set
            {
                ViewState["Sort_Filter"] = value.ToString();
            }
        }


        [CategoryAttribute("排序设置"),
        Bindable(true),
        DefaultValue("Single"),
        Description("设置排序方式,Sinle单行移动，Multi多行移动，Input用户指定排序序号"),
        Localizable(true)]
        public SortStyleItems SortStyle
        {
            get
            {
                if (ViewState["SortStyle"] == null || ViewState["SortStyle"].ToString() == "")
                    return SortStyleItems.Single;
                return (SortStyleItems)ViewState["SortStyle"];
            }
            set
            {
                ViewState["SortStyle"] = value;
            }
        }
        public enum SortStyleItems
        {
            Single = 0,
            Multi = 1,
            Input = 2,
        }

        [CategoryAttribute("排序列名"),
        Bindable(true),
        DefaultValue(""),
        Description("设置排序列名"),
        Localizable(true)]
        public string SortField
        {
            get
            {
                return (String)ViewState["SortField"];
            }
            set
            {
                ViewState["SortField"] = value.ToString();
            }
        }
        #endregion


        #region 重写控件
        protected override void CreateChildControls()
        {
            Controls.Clear();
            if (this.ItemID == -1)
            {
                Label msg = new Label();
                msg.ForeColor = Color.Red;
                msg.Font.Size = 8;
                msg.Text = "必须给ItemID（当前唯一编号）绑定值";
                Controls.Add(msg);
            }
            else if (string.IsNullOrWhiteSpace(this.KeyField))
            {
                Label msg = new Label();
                msg.ForeColor = Color.Red;
                msg.Font.Size = 8;
                msg.Text = "必须指定KeyField（唯一编号列名）";
                Controls.Add(msg);
            }
            else if (string.IsNullOrWhiteSpace(this.TableName))
            {
                Label msg = new Label();
                msg.ForeColor = Color.Red;
                msg.Font.Size = 8;
                msg.Text = "必须指定操作的表名";
                Controls.Add(msg);
            }
            else if (string.IsNullOrWhiteSpace(this.SortField))
            {
                Label msg = new Label();
                msg.ForeColor = Color.Red;
                msg.Font.Size = 8;
                msg.Text = "必须指定用作排序的序号列列名";
                Controls.Add(msg);
            }
            else if (this.ItemID != -1 && !string.IsNullOrWhiteSpace(this.KeyField) && !string.IsNullOrWhiteSpace(this.TableName) && !string.IsNullOrWhiteSpace(this.SortField))
            {
                switch (this.SortStyle)
                {
                    case SortStyleItems.Single:
                        Button btn_upmove = new Button();
                        btn_upmove.Text = "上移";
                        btn_upmove.Click += btn_Click_Pre;
                        this.Controls.Add(btn_upmove);
                        btn_upmove.Attributes.Add("style","margin-right:3px;");

                        Button btn_downmove = new Button();
                        btn_downmove.Text = "下移";
                        btn_downmove.Click += btn_Click_Next;
                        this.Controls.Add(btn_downmove);
                        break;
                    case SortStyleItems.Multi:
                        if (this.RowIndex == -1)
                        {
                            Label msg = new Label();
                            msg.ForeColor = Color.Red;
                            msg.Font.Size = 8;
                            msg.Text = "使用Multi样式必须要给RowIndex(行号)绑定值，示例：<%#Container.ItemIndex %>";
                            Controls.Add(msg);
                        }
                        else if (this.RowCount == 0)
                        {
                            Label msg = new Label();
                            msg.ForeColor = Color.Red;
                            msg.Font.Size = 8;
                            msg.Text = "使用Multi样式必须要给RowCount(行数)绑定值,即当前数据源的行数。";
                            Controls.Add(msg);
                        }
                        else if (this.RowIndex != -1 && this.RowCount != 0)
                        {
                            DropDownList select_pre = new DropDownList();
                            select_pre.EnableViewState = true;
                            select_pre.AutoPostBack = true;
                            select_pre.ID = "Sort_select_pre";

                            this.Controls.Add(select_pre);
                            for (int i = -1; i <= this.RowIndex; i++)
                            {
                                select_pre.Items.Add(new ListItem("上移" + (i + 1), (i + 1).ToString()));
                            }
                            select_pre.SelectedIndexChanged += select_pre_SelectedIndexChanged;


                            DropDownList select_next = new DropDownList();
                            select_next.EnableViewState = true;
                            select_next.AutoPostBack = true;

                            select_next.ID = "Sort_select_next";
                            this.Controls.Add(select_next);
                            for (int n = this.RowCount - this.RowIndex; n >= 0; n--)
                            {
                                select_next.Items.Add(new ListItem("下移" + n, n.ToString()));
                                select_next.SelectedIndex = this.RowCount - this.RowIndex;
                            }
                            select_next.SelectedIndexChanged += new EventHandler(select_next_SelectedIndexChanged);

                        }
                        break;
                    case SortStyleItems.Input:
                        if (this.Sort == -1)
                        {
                            Label msg = new Label();
                            msg.ForeColor = Color.Red;
                            msg.Font.Size = 8;
                            msg.Text = "使用Input样式必须要给Sort(序号)绑定值,即当前序号。";
                            Controls.Add(msg);
                        }
                        else
                        {
                            TextBox txt = new TextBox();
                            txt.ID = "Sort_input_pre";
                            txt.Attributes.Add("onfocus", "this.select();");
                             txt.Attributes.Add("style", "text-align:center;");
                            //txt.Attributes.Add("onblur",@"var reg = /^([1-9]\d*)$/;if (this.value.match(reg) == null){alert('只能输入整数！');return false;}");
                            txt.Width = 40;
                            txt.AutoPostBack = true;
                            txt.Text = this.Sort.ToString();
                            txt.TextChanged += txt_TextChanged;
                            this.Controls.Add(txt);
                        }
                        break;
                }
            }
            base.CreateChildControls();
        }
        #endregion
        #region 事件处理
        protected virtual void txt_TextChanged(object sender, EventArgs e)
        {
            TextBox cell = sender as TextBox;
            Regex r = new Regex(@"^[-+]?(?:(?:0(?!\d))|[1-9])\d*$", RegexOptions.Compiled);
            Match m = r.Match(cell.Text);
            if (!m.Success)
            {
                cell.Text = "错误！";
                cell.ForeColor = Color.Red;
                cell.Focus();
                return;
            }
            else
                cell.ForeColor = Color.Black;
            int movecount = Convert.ToInt32(cell.Text);
            int key = this.ItemID;
            if (SortControlManager.Input_Move(this.TableName, this.KeyField, key, this.SortField, movecount))
                SortCallBack_Event(cell, e);
        }
        /// <summary>
        /// 下拉列表上移
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void select_pre_SelectedIndexChanged(object sender, EventArgs e)
        {
            DropDownList cell = sender as DropDownList;
            int movecount = Convert.ToInt32(cell.SelectedValue);
            if (movecount == 0)
                return;
            int key = this.ItemID;
            string msg = null;
            if (SortControlManager.Drop_UpMove(this.TableName, this.KeyField, key, this.SortField, movecount, this.Filter, out msg))
            {
                SortCallBack_Event(cell, e);
            }
        }
        /// <summary>
        /// 下拉列表下移
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void select_next_SelectedIndexChanged(object sender, EventArgs e)
        {
            DropDownList cell = sender as DropDownList;
            int movecount = Convert.ToInt32(cell.SelectedValue);
            if (movecount == 0)
                return;
            int key = this.ItemID;
            string msg = null;
            if (SortControlManager.Drop_DownMove(this.TableName, this.KeyField, key, this.SortField, movecount, this.Filter, out msg))
            {
                SortCallBack_Event(cell, e);
            }
        }

        /// <summary>
        /// 单击按钮上移
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void btn_Click_Pre(object sender, EventArgs e)
        {
            Button cell = sender as Button;
            string msg = null;
            if (SortControlManager.Click_UpMove(this.TableName, this.KeyField, this.ItemID, this.SortField, this.Filter, out msg))
            {
                SortCallBack_Event(cell, e);
            }
            else
            {
                //失败
            }
        }
        /// <summary>
        /// 单击按钮下移
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void btn_Click_Next(object sender, EventArgs e)
        {
            Button cell = sender as Button;
            string msg = null;
            if (SortControlManager.Click_DownMove(this.TableName, this.KeyField, this.ItemID, this.SortField, this.Filter, out msg))
            {
                SortCallBack_Event(cell, e);
            }
            else
            {
                //失败
            }
        }
        #endregion

        #region 自定义事件
        //定义委托
        public delegate void SortCallBackHandle(object sender, EventArgs e);
        //定义事件
        public event SortCallBackHandle SortCallBack;
        private void SortCallBack_Event(object sender, EventArgs e)
        {
            if (SortCallBack != null)
                SortCallBack(sender, e);//自身作为参数传递
        }
        #endregion
    }
    public class SortControlManager
    {
        #region 数据排序
        public static bool Click_UpMove(string table, string key, int id, string sort, string where, out string msg)
        {
            bool r = false;
            msg = "";
            if (where != null && where.ToString() != "")
                where = " and " + where + " ";
            string sql = "select top 1 " + key + "," + sort + ",(select " + sort + " from " + table + " where " + key + "=" + id + where + ") as thissort from " + table + "  where " + sort + "<(select " + sort + " from " + table + "  where " + key + "=" + id + where + ") " + where + " order by " + sort + " desc";
            DataTable dt = DbHelper.ExecuteDataset(CommandType.Text, sql).Tables[0];
            if (dt.Rows.Count > 0)
            {
                string sql_1 = "";
                sql_1 += "begin transaction declare @errorSum int ";
                sql_1 += "update " + table + "  set " + sort + "=" + dt.Rows[0][sort].ToString() + " where " + key + "=" + id + where;//当前记录
                sql_1 += " set @errorSum=@errorSum+@@error    ";
                sql_1 += "update " + table + "  set " + sort + "=" + dt.Rows[0]["thissort"].ToString() + " where " + key + "=" + dt.Rows[0][key].ToString() + where;//当前记录
                sql_1 += " set @errorSum=@errorSum+@@error ";
                sql_1 += @" if @errorSum>0
                            begin
                                rollback transaction
                            end
                           else
                            begin
                                commit transaction
                            end";
                r = Convert.ToBoolean(DbHelper.ExecuteNonQuery(CommandType.Text, sql_1));
            }
            else
            {
                msg = "已经是第一条了！";
            }
            return r;
        }
        public static bool Click_DownMove(string table, string key, int id, string sort, string where, out string msg)
        {
            bool r = false;
            msg = "";
            if (where != null && where.ToString() != "")
                where = " and " + where + " ";
            string sql = "select top 1 " + key + "," + sort + ",(select " + sort + " from " + table + " where " + key + "=" + id + where + ") as thissort from " + table + "  where " + sort + ">(select " + sort + " from " + table + "  where " + key + "=" + id + where + ")" + where + " order by " + sort + " asc";
            DataTable dt = DbHelper.ExecuteDataset(CommandType.Text, sql).Tables[0];
            if (dt.Rows.Count > 0)
            {
                string sql_1 = "";
                sql_1 += "begin transaction declare @errorSum int ";
                sql_1 += "update " + table + "  set " + sort + "=" + dt.Rows[0][sort].ToString() + " where " + key + "=" + id + where;//当前记录
                sql_1 += " set @errorSum=@errorSum+@@error    ";
                sql_1 += "update " + table + "  set " + sort + "=" + dt.Rows[0]["thissort"].ToString() + " where " + key + "=" + dt.Rows[0][key].ToString() + where;//当前记录
                sql_1 += " set @errorSum=@errorSum+@@error ";
                sql_1 += @" if @errorSum>0
                            begin
                                rollback transaction
                            end
                           else
                            begin
                                commit transaction
                            end";
                r = Convert.ToBoolean(DbHelper.ExecuteNonQuery(CommandType.Text, sql_1));
            }
            else
            {
                msg = "已经是最后一条了！";
            }
            return r;
        }

        public static bool Drop_UpMove(string table, string key, int id, string sort, int sortCount, string where, out string msg)
        {
            bool r = false;
            msg = "";
            if (where != null && where.ToString() != "")
                where = " and " + where + " ";
            string sql = @"declare @id int
set @id=" + id + @"
declare @movecount int
set @movecount=" + sortCount + @"

select top (@movecount) " + key + @"," + sort + @" into #t1 from " + table + @" where " + sort + @"<(select " + sort + @" from " + table + @" where " + key + @"=@id " + where + @") order by " + sort + @" desc

declare @targetSort int
set @targetSort=( select top 1 " + sort + @"  from #t1 order by  " + sort + @" asc)
print @targetSort
if @targetSort is not null
begin
   
  begin transaction 
    declare @errorSum int
    update " + table + @"  set " + sort + @"=@targetSort where " + key + @"=@id
     set @errorSum=@errorSum+@@error
    update " + table + @" set " + sort + @"=(" + sort + @"+1) where  " + key + @" in (select " + key + @" from #t1)
     set @errorSum=@errorSum+@@error
   if @errorSum>0
                            begin
                                rollback transaction
                            end
                           else
                            begin
                                commit transaction
                            end
end
drop table #t1";
            r = Convert.ToBoolean(DbHelper.ExecuteNonQuery(CommandType.Text, sql));
            return r;

        }

        public static bool Drop_DownMove(string table, string key, int id, string sort, int sortCount, string where, out string msg)
        {
            bool r = false;
            msg = "";
            if (where != null && where.ToString() != "")
                where = " and " + where + " ";
            string sql = @"declare @id int
set @id=" + id + @"
declare @movecount int
set @movecount=" + sortCount + @"

select top (@movecount) " + key + @"," + sort + @" into #t1 from " + table + @" where " + sort + @">(select " + sort + @" from " + table + @" where " + key + @"=@id " + where + @") order by " + sort + @" asc

declare @targetSort int
set @targetSort=( select top 1 " + sort + @"  from #t1 order by  " + sort + @" desc)
print @targetSort
if @targetSort is not null
begin
   
  begin transaction 
    declare @errorSum int
    update " + table + @"  set " + sort + @"=@targetSort where " + key + @"=@id
     set @errorSum=@errorSum+@@error
    update " + table + @" set " + sort + @"=(" + sort + @"-1) where  " + key + @" in (select " + key + @" from #t1)
     set @errorSum=@errorSum+@@error
   if @errorSum>0
                            begin
                                rollback transaction
                            end
                           else
                            begin
                                commit transaction
                            end
end
drop table #t1";
            r = Convert.ToBoolean(DbHelper.ExecuteNonQuery(CommandType.Text, sql));
            return r;

        }

        public static bool Input_Move(string table, string key, int id, string sort, int SortVulue)
        {
            bool r = false;
            string sql = "update " + table + "  set " + sort + "=" + SortVulue + " where " + key + "=" + id;
            r = Convert.ToBoolean(DbHelper.ExecuteNonQuery(CommandType.Text, sql));
            return r;
        }
        #endregion
    }
}
